package com.hsurosy.domain.strategy.service.rule.chain.factory;

import com.hsurosy.domain.strategy.model.entity.StrategyEntity;
import com.hsurosy.domain.strategy.repository.IStrategyRepository;
import com.hsurosy.domain.strategy.service.rule.chain.ILogicChain;
import lombok.*;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author Hsu琛君珩
 * @Date 2024-10-19 1:43
 * @Description 默认责任链工厂。负责构建和管理责任链，将各节点按顺序链接
 * @Version: v1.0.0
 */
@Service
public class DefaultChainFactory {

    /** 原型模式获取对象 */
    private final ApplicationContext applicationContext;

    /** 存储所有可用的责任链节点 */
    private final Map<Long, ILogicChain> strategyChainGroup; // "rule_blacklist": BlackListLogicChain, "rule_weight": RuleWeightLogicChain, "default": DefaultLogicChain

    /** 抽奖策略仓储服务，用于查询策略和规则模型 */
    private final IStrategyRepository strategyRepository;

    // 构造函数，注入依赖
    public DefaultChainFactory(ApplicationContext applicationContext, IStrategyRepository strategyRepository) {
        this.applicationContext = applicationContext;
        this.strategyRepository = strategyRepository;
        this.strategyChainGroup = new ConcurrentHashMap<>();
    }

    /**
     * 打开指定策略的责任链
     * 该方法根据策略ID查询该策略的规则模型，并根据规则模型依次构建责任链
     *
     * @param strategyId 抽奖策略ID
     * @return 构建好的责任链的起始节点
     */
    public ILogicChain openLogicChain(Long strategyId) {
        ILogicChain cacheLogicChain = strategyChainGroup.get(strategyId);
        if (null != cacheLogicChain) {
            return cacheLogicChain;
        }

        // 1. 查询策略ID对应的抽奖策略实体，获取该策略下的规则模型列表
        StrategyEntity strategy = strategyRepository.queryStrategyEntityByStrategyId(strategyId);
        String[] ruleModels = strategy.ruleModels();  // 获取该策略的规则模型

        // 2. 如果没有定义规则模型，则返回默认的责任链
        if (null == ruleModels || ruleModels.length == 0) {
            ILogicChain ruleDefaultLogicChain = applicationContext.getBean(LogicModel.RULE_DEFAULT.getCode(), ILogicChain.class);
            // 写入缓存
            strategyChainGroup.put(strategyId, ruleDefaultLogicChain);
            return ruleDefaultLogicChain;
        }

        // 3. 初始化责任链，从第一个规则模型开始
        ILogicChain logicChain = applicationContext.getBean(ruleModels[0], ILogicChain.class);
        ILogicChain current = logicChain;

        // 4. 依次追加后续的规则模型，构建完整的责任链
        for (int i = 1; i < ruleModels.length; i++) {
            ILogicChain nextChain = applicationContext.getBean(ruleModels[i], ILogicChain.class);  // 获取下一个规则模型对应的责任链节点
            current = current.appendNext(nextChain);  // 将当前节点与下一个节点连接
        }

        // 5. 追加默认责任链，作为责任链的最后一步
        current.appendNext(applicationContext.getBean(LogicModel.RULE_DEFAULT.getCode(), ILogicChain.class));

        // 写入缓存
        strategyChainGroup.put(strategyId, logicChain);

        // 6. 返回构建好的责任链的起始节点
        return logicChain;
    }

    /**
     * 数据传输对象，封装了责任链执行的结果
     */
    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    public static class StrategyAwardVO {
        /** 抽奖奖品ID - 由责任链流转使用 */
        private Integer awardId;
        /** 抽奖的规则模型，用于标记奖品的抽取方式 */
        private String logicModel;
        /** 抽奖奖品规则 */
        private String awardRuleValue;
    }

    /**
     * 枚举类，定义了不同的责任链处理模型。
     * 每个模型代表一种抽奖规则，例如黑名单抽奖、权重抽奖等。
     */
    @Getter
    @AllArgsConstructor
    public enum LogicModel {

        RULE_DEFAULT("rule_default", "默认抽奖"),
        RULE_BLACKLIST("rule_blacklist", "黑名单抽奖"),
        RULE_WEIGHT("rule_weight", "权重规则"),
        ;

        private final String code;
        private final String info;
    }

}
